/**
 * @file ble_multi_central.h
 * @brief BLE多连接中心设备库头文件
 */

#ifndef BLE_MULTI_CENTRAL_H__
#define BLE_MULTI_CENTRAL_H__

#include <stdint.h>

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/kernel.h>

#ifdef __cplusplus
extern "C" {
#endif

// 配置项
#define BLE_MAX_CONNECTIONS 8          // 最大连接数
#define BLE_MAX_SERVICES_PER_DEV 5     // 每个设备最大服务数
#define BLE_MAX_CHARS_PER_SERVICE 10   // 每个服务最大特征值数
#define BLE_MAX_DESCS_PER_CHAR 5       // 每个特征值最大描述符数
#define BLE_MAX_AUTO_CONNECT_RETRIES 5 // 自动重连最大尝试次数
#define BLE_AUTO_CONNECT_RETRY_INTERVAL K_MSEC(1000) // 重连间隔
#define BLE_CONNECTION_TIMEOUT K_SECONDS(30)         // 连接超时时间

#define BLE_ERR_BUSY (-EBUSY)
#define BLE_ERR_TIMEOUT (-ETIMEDOUT)

// 前向声明
struct ble_central_dev;
struct ble_gatt_service;
struct ble_gatt_char;
struct ble_gatt_desc;

typedef struct bt_uuid bt_uuid_t;

// 回调函数类型定义
typedef void (*ble_central_connect_cb_t)(struct ble_central_dev *dev,
                                         void *user_data);
typedef void (*ble_central_disconnect_cb_t)(struct ble_central_dev *dev,
                                            uint8_t reason, void *user_data);
typedef void (*ble_data_received_cb_t)(struct ble_central_dev *dev,
                                       struct ble_gatt_char *characteristic,
                                       const uint8_t *data, uint16_t len,
                                       void *user_data);

// GATT描述符结构
struct ble_gatt_desc {
  union {
    bt_uuid_t uuid;             // 基本 UUID 类型
    struct bt_uuid_16 uuid16;   // 16位 UUID
    struct bt_uuid_32 uuid32;   // 32位 UUID
    struct bt_uuid_128 uuid128; // 128位 UUID
  } uuid_data;
  uint16_t handle;
  bool valid;
};

// GATT特征值结构
struct ble_gatt_char {
  union {
    bt_uuid_t uuid;
    struct bt_uuid_16 uuid16;
    struct bt_uuid_32 uuid32;
    struct bt_uuid_128 uuid128;
  } uuid_data;
  uint16_t handle;
  uint16_t value_handle;
  uint8_t properties;
  uint16_t ccc_handle;
  bool notify_enabled;
  bool indicate_enabled;

  // 描述符数组
  struct ble_gatt_desc descriptors[BLE_MAX_DESCS_PER_CHAR];
  uint8_t desc_count;

  bool valid;
};

// GATT服务结构
struct ble_gatt_service {
  union {
    bt_uuid_t uuid;
    struct bt_uuid_16 uuid16;
    struct bt_uuid_32 uuid32;
    struct bt_uuid_128 uuid128;
  } uuid_data;
  uint16_t start_handle;
  uint16_t end_handle;

  // 特征值数组
  struct ble_gatt_char characteristics[BLE_MAX_CHARS_PER_SERVICE];
  uint8_t char_count;

  bool valid;
};

// 设备连接结构
struct ble_central_dev {
  bt_addr_le_t addr;
  struct bt_conn *conn;
  bool connected;

  // GATT缓存
  struct ble_gatt_service services[BLE_MAX_SERVICES_PER_DEV];
  uint8_t service_count;

  bool discovery_complete;
  bool in_use;
  uint8_t index; // 设备索引

  bool auto_reconnect;                          // 是否自动重连
  uint8_t reconnect_attempts;                   // 重连尝试次数
  bool connecting;                              // 连接中标志
  struct k_work_delayable connect_timeout_work; // 连接超时工作
  struct k_work_delayable retry_work;           // 重试工作
};

// 库初始化配置
struct ble_central_config {
  // 要扫描的服务UUID列表
  const bt_uuid_t **target_service_uuids;
  uint8_t service_uuid_count;

  // 回调函数
  ble_central_connect_cb_t connect_cb;
  ble_central_disconnect_cb_t disconnect_cb;
  ble_data_received_cb_t data_cb;

  // 用户数据，会在回调中传递
  void *user_data;
};

/**
 * @brief 初始化BLE多连接中心设备库
 *
 * @param config 配置参数
 * @return 0表示成功，负值表示错误码
 */
int ble_central_init(const struct ble_central_config *config);

/**
 * @brief 开始扫描BLE设备
 *
 * @return 0表示成功，负值表示错误码
 */
int ble_central_start_scan(void);

/**
 * @brief 停止扫描BLE设备
 *
 * @return 0表示成功，负值表示错误码
 */
int ble_central_stop_scan(void);

/**
 * @brief 连接到指定BLE设备
 *
 * @param addr 设备地址
 * @param dev_index 如果连接成功，将填充设备索引
 * @return 0表示成功，负值表示错误码
 */
int ble_central_connect(const bt_addr_le_t *addr, uint8_t *dev_index);

/**
 * @brief 断开与指定设备的连接
 *
 * @param dev_index 设备索引
 * @return 0表示成功，负值表示错误码
 */
int ble_central_disconnect(uint8_t dev_index);

/**
 * @brief 通过索引获取设备
 *
 * @param dev_index 设备索引
 * @return 设备指针，如果索引无效则返回NULL
 */
struct ble_central_dev *ble_central_get_device(uint8_t dev_index);

/**
 * @brief 获取所有连接设备的数量
 *
 * @return 已连接设备数量
 */
uint8_t ble_central_get_connected_count(void);

/**
 * @brief 发现设备的服务和特征值
 *
 * @param dev_index 设备索引
 * @return 0表示成功，负值表示错误码
 */
int ble_central_discover_services(uint8_t dev_index);

/**
 * @brief 通过UUID查找服务
 *
 * @param dev_index 设备索引
 * @param uuid 服务UUID
 * @return 服务指针，未找到则返回NULL
 */
struct ble_gatt_service *ble_central_find_service(uint8_t dev_index,
                                                  const bt_uuid_t *uuid);

/**
 * @brief 通过UUID查找特征值
 *
 * @param service 服务指针
 * @param uuid 特征值UUID
 * @return 特征值指针，未找到则返回NULL
 */
struct ble_gatt_char *
ble_central_find_characteristic(struct ble_gatt_service *service,
                                const bt_uuid_t *uuid);

/**
 * @brief 通过UUID查找描述符
 *
 * @param characteristic 特征值指针
 * @param uuid 描述符UUID
 * @return 描述符指针，未找到则返回NULL
 */
struct ble_gatt_desc *
ble_central_find_descriptor(struct ble_gatt_char *characteristic,
                            const bt_uuid_t *uuid);

/**
 * @brief 写入特征值数据
 *
 * @param dev_index 设备索引
 * @param service_uuid 服务UUID
 * @param char_uuid 特征值UUID
 * @param data 数据缓冲区
 * @param len 数据长度
 * @param response 是否需要响应
 * @return 0表示成功，负值表示错误码
 */
int ble_central_write_characteristic(uint8_t dev_index,
                                     const bt_uuid_t *service_uuid,
                                     const bt_uuid_t *char_uuid,
                                     const uint8_t *data, uint16_t len,
                                     bool response);

/**
 * @brief 读取特征值数据
 *
 * @param dev_index 设备索引
 * @param service_uuid 服务UUID
 * @param char_uuid 特征值UUID
 * @param data 数据缓冲区
 * @param len 缓冲区大小，返回实际读取的数据长度
 * @return 0表示成功，负值表示错误码
 */
int ble_central_read_characteristic(uint8_t dev_index,
                                    const bt_uuid_t *service_uuid,
                                    const bt_uuid_t *char_uuid, uint8_t *data,
                                    uint16_t *len);

/**
 * @brief 启用或禁用通知
 *
 * @param dev_index 设备索引
 * @param service_uuid 服务UUID
 * @param char_uuid 特征值UUID
 * @param enable 是否启用
 * @return 0表示成功，负值表示错误码
 */
int ble_central_enable_notifications(uint8_t dev_index,
                                     const bt_uuid_t *service_uuid,
                                     const bt_uuid_t *char_uuid, bool enable);

/**
 * @brief 启用或禁用指示
 *
 * @param dev_index 设备索引
 * @param service_uuid 服务UUID
 * @param char_uuid 特征值UUID
 * @param enable 是否启用
 * @return 0表示成功，负值表示错误码
 */
int ble_central_enable_indications(uint8_t dev_index,
                                   const bt_uuid_t *service_uuid,
                                   const bt_uuid_t *char_uuid, bool enable);

/**
 * @brief 配置设备是否启用自动重连
 *
 * @param dev_index 设备索引
 * @param enable 是否启用自动重连
 * @return 0表示成功，负值表示错误码
 */
int ble_central_set_auto_reconnect(uint8_t dev_index, bool enable);

/**
 * @brief 检查设备连接状态
 *
 * @param dev_index 设备索引
 * @param connecting 输出参数，指示设备是否正在连接中
 * @param connected 输出参数，指示设备是否已连接
 * @return 0表示成功，负值表示错误码
 */
int ble_central_get_connection_state(uint8_t dev_index, bool *connecting,
                                     bool *connected);

/**
 * @brief 重置连接错误状态
 *
 * @param dev_index 设备索引
 * @return 0表示成功，负值表示错误码
 */
int ble_central_reset_connection_state(uint8_t dev_index);

#ifdef __cplusplus
}
#endif

#endif /* BLE_MULTI_CENTRAL_H__ */
